#ifndef NOSAL_EXEC_INTERNAL_PROCESSED_SET_STATE_REQUEST_H_
#define NOSAL_EXEC_INTERNAL_PROCESSED_SET_STATE_REQUEST_H_

#include "dependency_calculator.h"
#include "startup_configuration.h"
//#include "state_client_impl.h"

namespace netaos {
namespace nosal {
namespace exec {
namespace internal {

/// @brief Helper enum representing EM-internal information about the Startup attempts of a process
///
/// @note the order is important as EM will compare different values
enum class StartupStatus
{
    kFailed,  ///< startup failed.
    kRunning,  ///< process has reached state running.
    kReady,  ///< process is ready to be started after all dependencies are satisfied.
    kStarting,  /// process has started, but is not yet in state Running.
    kTerminating,  ///< process has received SIGTERM after failed start.
    kTerminated  ///< process has terminated again after failed start.
};

enum class SetStateFailureCause
{
    kConfigurationError,  ///< there is some configuration error.
    kEnterTimeout,  ///< an enter timeout occured.
    kNotStarted,  ///< Process couldn't be started.
    kUnexpectedTerminationOnEnter  ///< Process terminated unexpectedly during start.
};

/// @brief Helper struct to store information about a currently processed transition to a new FunctionGroupState.
struct ProcessedSetStateRequest
{
    ProcessedSetStateRequest()
        : ongoingSetState(false)
        , stateFailureOccured(false)
        , unexpectedTerminationOnEnterOccured(false)
        , timeoutOccured(false)
        , ongoingExecute(false)
    { }

    ProcessedSetStateRequest(const std::string& functionGroupName, const std::string& stateName)
        : /*request(StateClientImpl::SetStateRequest{functionGroupName,
            stateName,
            std::chrono::time_point<std::chrono::steady_clock>{}})
        , */ongoingSetState(false)
        , stateFailureOccured(false)
        , unexpectedTerminationOnEnterOccured(false)
        , timeoutOccured(false)
        , ongoingExecute(false)
    { }
#if 0
    /// @brief The initial request that was received via the StateClient API.
    //StateClientImpl::SetStateRequest request;
#endif
    /// @brief The StartupConfiguration that issued the request (should be the StateManager)
    std::shared_ptr<StartupConfiguration> requestor;
    /// @brief A flag that indicates if the initialization of the SetState method happened.
    bool ongoingSetState;
    /// @brief A flag if the termination of required Processes is ongoing.
    bool ongoingTerminate;
    /// @brief Flag for occurred state change failures.
    bool stateFailureOccured;
    /// @brief Flag for unexpected terminations during startup.
    bool unexpectedTerminationOnEnterOccured;
    /// @brief Flag for timeouts.
    bool timeoutOccured;
    /// @brief The required changes for the state change, constisting of terminations and starts.
    TransitionChanges transitionChanges;
    /// @brief The FunctionGroup to change from the set state request.
    FunctionGroup* functionGroup;
    /// @brief The target state.
    std::string state;
    /// @brief A flag that indicates if the initialization of the Execute method happened.
    bool ongoingExecute;
    /// @brief A flag that indicates if resparsing of execution manifests happened.
    bool reparsingIsHandled;
    /// @brief A map of StartupConfiguration names and their (local to the Execute method) Startup state.
    std::map<std::string, StartupStatus> startupCheckResults;
    /// @brief A map of StartupConfiguration names and their maximum allowed number of restart retries.
    std::map<std::string, std::uint32_t> maxNumberOfRetries;
    /// @brief A map of StartupConfiguration names and their current number of start attempts.
    std::map<std::string, std::uint32_t> numberOfAttempts;
    /// @brief A map of StartupConfiguration names and a flag to indicate that it has been started but terminated in the
    /// meantime.
    std::map<std::string, bool> startedAndTerminated;
    /// @brief Information about the process and error in case of a state transition failure.
    netaos::nosal::core::Optional<std::pair<std::shared_ptr<StartupConfiguration>, SetStateFailureCause>> failureInformation;
};

}  // namespace internal
}  // namespace exec
}  // namespace nosal
}  // namespace netaos

#endif  // NOSAL_EXEC_INTERNAL_PROCESSED_SET_STATE_REQUEST_H_
